package com.bbzn.device.client.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.bbzn.device.client.vo.res.DeviceUsed;
import com.bbzn.device.client.vo.res.DeviceUsedVO;
import com.bbzn.device.client.vo.res.FireIndexVO;
import com.bbzn.device.client.vo.res.SupervisorsIndexVO;
import com.bbzn.device.client.dataobject.FireImage;
import com.bbzn.device.client.dto.device.DeviceCountDTO;
import com.bbzn.device.client.dto.device.FireIndexDTO;
import com.bbzn.device.client.service.DeviceService;
import com.bbzn.device.client.service.FireImageService;
import com.bbzn.device.client.service.IndexService;
import com.bbzn.device.client.utils.BeanVOUtils;
import com.bbzn.device.client.utils.RedisUtils;
import com.bbzn.device.client.utils.date.DateUtil;
import com.bbzn.user.comment.User;
import com.bbzn.user.comment.res.UserRes;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class IndexServiceImpl implements IndexService {

    @Autowired
    public RedisUtils redisUtils;

    @Autowired
    public DeviceService deviceService;

    @Autowired
    public FireImageService fireImageService;

    @Override
    public void indexSevDayBeforeRedis() {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<Date> dates = DateUtil.getDaysBetwwen(30);
        String date = DateUtil.dateToString(dates.get(0));

        Set<String> visitsSet = redisUtils.keys("visitsCount:*");
        visitsSet.stream().forEach(visits -> {
            String[] split = visits.split(":");
            try {
                if(dateFormat.parse(split[2]).getTime() < dateFormat.parse(date).getTime()){
                    redisUtils.delete(visits);
                }
            } catch (ParseException e) {
                log.info("visitsCount- 数据处理异常：" + e.getMessage());
                e.printStackTrace();
            }
        });

        Set<String> deviceUsedSet = redisUtils.keys("DeviceUsedCount:*");
        deviceUsedSet.stream().forEach(deviceUsed -> {
            String[] split = deviceUsed.split(":");
            try {
                if(dateFormat.parse(split[2]).getTime() < dateFormat.parse(date).getTime()){
                    redisUtils.delete(deviceUsed);
                }
            } catch (ParseException e) {
                log.info("DeviceUsedCount- 数据处理异常：" + e.getMessage());
                e.printStackTrace();
            }
        });

        Set<String> helmetDevUsedSet = redisUtils.keys("HelmetDevUsedCount:*");
        helmetDevUsedSet.stream().forEach(helmetDevUsed -> {
            String[] split = helmetDevUsed.split(":");
            try {
                if(dateFormat.parse(split[2]).getTime() < dateFormat.parse(date).getTime()){
                    redisUtils.delete(helmetDevUsed);
                }
            } catch (ParseException e) {
                log.info("HelmetDevUsedCount- 数据处理异常：" + e.getMessage());
                e.printStackTrace();
            }
        });
    }

    @Override
    public FireIndexVO parseFireIndexVO(List<Long> ids,Long userId) {
        List<FireIndexDTO> dtos = deviceService.selectFireDevice(ids);
        if(CollectionUtils.isEmpty(dtos)){
            return null;
        }
        FireIndexVO fireIndexVO = new FireIndexVO(dtos);
        List<DeviceCountDTO> deviceCount = deviceService.selectFireDeviceCount(ids);
        if(CollectionUtils.isNotEmpty(dtos)){
            fireIndexVO.setDeviceCountDTOS(deviceCount);
        }
        if(null!=userId){
            ids.add(userId);
        }
        List<FireImage> fireImages = fireImageService.findByUserIds(ids);
        if(CollectionUtils.isNotEmpty(fireImages)){
            fireIndexVO.setFireImages(fireImages);
        }
        return fireIndexVO;
    }

    /**
     * 转化监管人首页数据
     * @param users
     * @return
     */
    public SupervisorsIndexVO parseSupervisorsIndexVO(List<UserRes> users){
        List<Long> userIds = users.stream().filter(BeanVOUtils.distinctByKey(User::getId)).map(User::getId).filter(Objects::nonNull).collect(Collectors.toList());
        SupervisorsIndexVO supervisorsIndexVO = new SupervisorsIndexVO(users);
        List<DeviceCountDTO> deviceCountDTOList = deviceService.selectFireDeviceCount(userIds);
        if(CollectionUtils.isNotEmpty(deviceCountDTOList)){
            supervisorsIndexVO.setDeviceCountDTOS(deviceCountDTOList);
        }
        Long onLiveCount = deviceCountDTOList.stream().filter(r->r.getState().equals(0)).count();
        Long downLiveCount = deviceCountDTOList.stream().filter(r->r.getState().equals(1)).count();
        Integer deviceCount = deviceCountDTOList.size();
        supervisorsIndexVO.setDownLineCount(downLiveCount);
        supervisorsIndexVO.setOnlineCount(onLiveCount);
        supervisorsIndexVO.setTotalDeviceCount(deviceCount);
        List<String> keys = new ArrayList<>();
        List<Date> dates = DateUtil.getDaysBetwwen(30);
        for (Date date : dates) {
            String dateStr = DateUtils.formatDate(date, "yyyy-MM-dd");
            for (Long userId : userIds) {
                String key  = "DeviceUsedCount:"+userId+":"+dateStr;
                keys.add(key);
            }
        }
        if(CollectionUtils.isNotEmpty(keys)){
            List<Map<String,String>> maps = redisUtils.hGetAllOfKeys(keys);
            List<DeviceUsedVO> vos = paresDeviceVOS(maps);
            if(null!=vos){
                supervisorsIndexVO.setDeviceUsedVOS(vos);
            }
        }
        return supervisorsIndexVO;
    }

    /**
     * 转换设使用量对象
     * @param maps
     * @return
     */
    private List<DeviceUsedVO> paresDeviceVOS(List<Map<String,String>> maps){
        List<DeviceUsedVO> vos = new ArrayList<>();
        if(null==maps || maps.size()==0){
            DeviceUsedVO vo = parseDefaultDeviceUsedVO();
            vos.add(vo);
            return vos;
        }
        maps.stream().parallel().forEach(map->{
            for (Map.Entry<String, String> stringStringEntry : map.entrySet()) {
                DeviceUsedVO vo = new DeviceUsedVO();
                List<DeviceUsed> deviceUseds = new ArrayList();
                String[] keys  = stringStringEntry.getKey().split(":");
                String date = keys[2];
                vo.setUsedDate(DateUtil.strToDate(date,"yyyy-MM-dd"));
                Map<String,String> values = JSON.parseObject(stringStringEntry.getValue(), new TypeReference<Map<String,String>>() {});
                for (Map.Entry<String, String> valesEntry : values.entrySet()) {
                    DeviceUsed deviceUsed = new DeviceUsed(valesEntry.getKey(),valesEntry.getValue());
                    deviceUseds.add(deviceUsed);
                }
                if(CollectionUtils.isNotEmpty(deviceUseds)){
                    vo.setUseds(deviceUseds);
                }
                vos.add(vo);
            }
        });
        if(CollectionUtils.isEmpty(vos)){
            DeviceUsedVO vo = parseDefaultDeviceUsedVO();
            vos.add(vo);
            return vos;
        }
        return vos;
    }

    private DeviceUsedVO parseDefaultDeviceUsedVO(){
        DeviceUsedVO vo = new DeviceUsedVO();
        List<DeviceUsed> deviceUseds = new ArrayList();
        DeviceUsed deviceUsed = new DeviceUsed();
        deviceUsed.setProductId("1008");
        deviceUsed.setUsedCount("0");
        deviceUseds.add(deviceUsed);
        vo.setUsedDate(new Date());
        vo.setUseds(deviceUseds);
        return vo;
    }
}
